package com.zmzncs.lmtc.module.order.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zmzncs.lmtc.common.pojo.LoginUser;
import com.zmzncs.lmtc.common.pojo.tengda.TengdaForm;
import com.zmzncs.lmtc.common.util.*;
import com.zmzncs.lmtc.module.customer.dao.CarDao;
import com.zmzncs.lmtc.module.customer.dao.CardDao;
import com.zmzncs.lmtc.module.customer.dao.CustomerDao;
import com.zmzncs.lmtc.module.customer.pojo.car.CarDTO;
import com.zmzncs.lmtc.module.customer.pojo.card.Card;
import com.zmzncs.lmtc.module.customer.pojo.card.CardDTO;
import com.zmzncs.lmtc.module.customer.pojo.customer.CustomerDTO;
import com.zmzncs.lmtc.module.order.dao.OrderCardDao;
import com.zmzncs.lmtc.module.order.dao.OrderInfoDao;
import com.zmzncs.lmtc.module.order.pojo.order_card.OrderCard;
import com.zmzncs.lmtc.module.order.pojo.order_card.OrderCardDTO;
import com.zmzncs.lmtc.module.order.pojo.order_info.OrderInfoDTO;
import com.zmzncs.lmtc.module.order.pojo.order_trade_record.PayBehalfForm;
import com.zmzncs.lmtc.module.order.pojo.order_trade_record.OrderTradeRecord;
import com.zmzncs.lmtc.module.order.dao.OrderTradeRecordDao;
import com.zmzncs.lmtc.module.order.pojo.order_trade_record.OrderTradeRecordDTO;
import com.zmzncs.lmtc.module.order.service.OrderTradeRecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zmzncs.lmtc.module.park.dao.ParkInfoDao;
import com.zmzncs.lmtc.module.park.pojo.parkinfo.ParkInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.http.impl.cookie.DateUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 订单-订单交易记录 服务实现类
 * </p>
 *
 * @author 任建波
 * @since 2020-09-24
 */
@Slf4j
@Service
public class OrderTradeRecordServiceImpl extends ServiceImpl<OrderTradeRecordDao, OrderTradeRecord> implements OrderTradeRecordService {

    @Autowired
    OrderTradeRecordDao orderTradeRecordDao;
    @Autowired
    CustomerDao customerDao;
    @Autowired
    OrderInfoDao orderInfoDao;
    @Autowired
    MpMessageUtil mpMessageUtil;
    @Autowired
    ParkInfoDao parkInfoDao;
    @Autowired
    CardDao cardDao;
    @Autowired
    CarDao cardao;
    @Autowired
    OrderCardDao orderCardDao;

    @Autowired
    HttpServletRequest request;

    @Value("${wechat.notify-url.behalfPay}")
    String behalfPayNotifyUrl;
    @Value("${pay-test}")
    boolean payTest;

    //  请求队列
    private static List<String> requestCatch = new ArrayList();

    //  支付垫付订单交易记录缓存
    public static List<Map<String, Object>> tradeRecordListCatch = new ArrayList<>();


    @Override
    public IPage<OrderTradeRecordDTO> getOrderTradeRecordRecharge(Page page) {
        LoginUser loginUser = JwtUtil.getLoginUser(request);
        IPage<OrderTradeRecordDTO> iPage = orderTradeRecordDao.getOrderTradeRecordRecharge(page,loginUser.getCustomerId());
        return iPage;
    }

    @Override
    public IPage<OrderTradeRecordDTO> getOrderTradeRecordBehalfPay(Page page) {
        LoginUser loginUser = JwtUtil.getLoginUser(request);
        IPage<OrderTradeRecordDTO> iPage = orderTradeRecordDao.getOrderTradeRecordBehalfPay(page,loginUser.getCustomerId());
        return iPage;
    }

    /**
     * 支付垫付金额
     */
    @Override
    @Transactional
    public Map<String, Object> behalfPay(PayBehalfForm form) {
        LoginUser loginUser = JwtUtil.getLoginUser(request);

        //  应支付金额
        BigDecimal payableAmount = new BigDecimal(0);
        //  校验金额
        for(Long tradeRecordId: form.getTradeRecordIdList()){
            OrderTradeRecord orderTradeRecord = orderTradeRecordDao.selectById(tradeRecordId);
            if(orderTradeRecord == null){
                ExceptionUtil.businessException("交易记录错误");
            }

            payableAmount = payableAmount.add(orderTradeRecord.getPaidAmount());
        }
        if(payableAmount.compareTo(form.getTotalAmount()) != 0){
            ExceptionUtil.businessException("支付金额错误");
        }

        //客户详情
        CustomerDTO customerDTO = customerDao.getCustomerById(loginUser.getCustomerId());
        //  订单号
        String orderCode = ChinaumsUtil.getMerOrderId("DF");
        //  支付金额
        BigDecimal paidAmount = payTest ? new BigDecimal("0.01") : form.getTotalAmount();
        //  车牌列表
        List<String> carNumberList = new ArrayList<>();
        for(Long orderTradeRecordId: form.getTradeRecordIdList()){
            OrderInfoDTO orderInfoDTO = orderInfoDao.getByOrderTradeRecordId(orderTradeRecordId);
            carNumberList.add(orderInfoDTO.getCarNumber());
        }

        //  支付
        JSONObject attach = new JSONObject();
        Map<String, Object> map = new HashMap();
        map.put("orderCode", orderCode);
        map.put("tradeRecordIdList", form.getTradeRecordIdList());
        map.put("carNumberList", carNumberList);
        tradeRecordListCatch.add(map);
        attach.put("orderCode", orderCode);
        attach.put("customerId", loginUser.getCustomerId());
        Map<String, Object> wxPay = WeChatUtil.wxPay(customerDTO.getOpenid(), behalfPayNotifyUrl, paidAmount, orderCode, attach.toJSONString(), "支付垫付");
        return wxPay;
    }

    /**
     * 垫付支付-回调
     */
    @Override
    @Transactional
    public String behalfPayCallback(String callbackStr) {
        //  解析微信返回值
        Map<String, String> callbackMap = null;
        try {
            callbackMap = XmlUtil.parseXML(callbackStr);
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 支付成功
        if ("SUCCESS".equals(callbackMap.get("return_code")) && "SUCCESS".equals(callbackMap.get("result_code"))) {
            String tradeNo = callbackMap.get("out_trade_no");    //  订单号
            try {
                log.info("缓存订单号：{}", requestCatch);
                if(requestCatch.contains(tradeNo)){
                    ExceptionUtil.businessException("微信支付回调-垫付支付-订单号【" + tradeNo + "】正在处理");
                } else {
                    requestCatch.add(tradeNo);
                }
                log.info("订单号：" + tradeNo);

                String attach = callbackMap.get("attach");  //  附加数据
                attach = StringEscapeUtils.unescapeJava(attach);    //  在处理字符串之前，先将字符串去除转义
                JSONObject attachJB = JSONObject.parseObject(attach);
                String orderCode = attachJB.getString("orderCode");
                String customerId = attachJB.getString("customerId");

                List<Long> tradeRecordIdList = new ArrayList<>();
                List<String> carNumberList = new ArrayList<>();
                for(Map<String, Object> map: tradeRecordListCatch){
                    if(map.get("orderCode").equals(orderCode)) {
                        tradeRecordIdList = JSONArray.parseArray(map.get("tradeRecordIdList").toString(), Long.class);
                        carNumberList = (List<String>) map.get("carNumberList");
//                        carNumberList = JSONArray.parseArray(map.get("carNumberList").toString(), String.class);
                    }
                }

                //  更新订单交易记录垫付状态
                for(int i=0; i<tradeRecordIdList.size(); i++){
                    //  根据车牌查询白天夜间卡
                    CardDTO dayNightMonth = cardDao.getDayNightMonthByCarNumber(Long.parseLong(customerId), carNumberList.get(i));
                    ParkInfo parkInfo = parkInfoDao.selectById(dayNightMonth.getParkId());
                    int flag = 0;
                    //  腾达停车场
                    if(parkInfo.getParkSource().equals(4)){
                        TengdaForm freeze = TengdaUtil.unfreeze(parkInfo.getBolianParkId(), dayNightMonth.getParkMonthId());
                        flag = freeze.getCode();
                    //  道尔停车场
                    }
//                    else if (parkInfo.getParkSource().equals(3)){
//                        Map<String, Object> map = DaoerApiUtil.lockUnlockCar(parkInfo.getBolianParkId(), carNumberList.get(i), 0);
//                        flag = (int) map.get("status");
//                    }
                    if(flag == 1) {
                        //  更新会员卡状态
                        Card card = new Card();
                        card.setId(dayNightMonth.getId());
                        card.setStatus(1);
                        cardDao.updateById(card);

                        Long tradeRecordId = tradeRecordIdList.get(i);
                        OrderTradeRecord tradeRecord = orderTradeRecordDao.selectById(tradeRecordId);
                        tradeRecord.setBehalfPayStatus(2);
                        orderTradeRecordDao.updateById(tradeRecord);
                    } else {
                        log.error("解冻月租卡失败");
                    }
                }

                //  删除缓存
                tradeRecordListCatch.removeIf(map -> map.get("orderCode").equals(orderCode));
                log.info("垫付支付-微信支付回调结束");
            } finally {
                requestCatch.remove(tradeNo);
            }
        }

        return WeChatUtil.wxpayCallbackResult(true);
    }

    /**
     * 欠费订单
     */
    @Override
    public List<OrderTradeRecordDTO> getArrearsOrder() {
        LoginUser loginUser = JwtUtil.getLoginUser(request);
        //  获取客户车辆
        List<CarDTO> carList = cardao.getCustomerCarList(loginUser.getCustomerId());
        List<String> carNumberList = carList.stream().map(CarDTO::getCarNumber).collect(Collectors.toList());

        //  获取客户欠费订单
        List<OrderTradeRecordDTO> arrearsOrderList = new ArrayList<>();
        if(carNumberList.size() > 0){
            arrearsOrderList  = orderTradeRecordDao.getArrearsOrder(carNumberList);
        }
        //  停车时长
        for(OrderTradeRecordDTO recordDTO: arrearsOrderList) {
            CardDTO dayNightMonthCard = cardDao.getDayNightMonthByCarNumber(loginUser.getCustomerId(), recordDTO.getCarNumber());
            recordDTO.setDayBeginTime(dayNightMonthCard.getDayBeginTime());
            recordDTO.setDayEndTime(dayNightMonthCard.getDayEndTime());
            long minute = DateTimeUtil.betweenMinute(recordDTO.getOutTime() == null ? new Date() : recordDTO.getOutTime(), recordDTO.getInTime());
            recordDTO.setParkDuration(minute);
        }
        return arrearsOrderList;
    }

}
